using System.Collections.Generic;
using UnityEngine;

[ExecuteInEditMode]
public class RemoteControl : MonoBehaviour
{
	public GameObject controller;

	public bool isActive = true;

	public RemoteControl placementParent;

	public Vector3 displacement;

	public bool manualDisplacement;

	public List<RemoteControl> placementChildren;

	public bool manualScale;

	public Vector3 scale;

	private static bool showPlacementBounds = true;

	public bool showChildrenBounds;

	public Transform remotesParent;

	public static bool pickParent;

	public static RemoteControl pickParentTarget;

	public static RemoteControl pickParentNew;

	[HideInInspector]
	public bool destroyable = true;

	[HideInInspector]
	public bool duplicable = true;

	[HideInInspector]
	public bool rotatable = true;

	public BoxAlignment alignX;

	public BoxAlignment alignY;

	public BoxAlignment alignZ;

	public float alignXOffset;

	public float alignYOffset;

	public float alignZOffset;

	private Bounds oldPlacementBounds;

	private Bounds oldPlacementParentBounds;

	private BoxAlignment alignXOld;

	private BoxAlignment alignYOld;

	private BoxAlignment alignZOld;

	private float alignXOffsetOld;

	private float alignYOffsetOld;

	private float alignZOffsetOld;

	private int recentUpdated;

	private void OnDrawGizmosSelected()
	{
		if (placementParent != null && !pickParent)
		{
			Bounds placementParentBounds = GetPlacementParentBounds();
			Gizmos.color = new Color(1f, 0f, 0f);
			DrawFatWireCube(placementParentBounds.center, placementParentBounds.size);
		}
		if (pickParent && pickParentNew != null)
		{
			Bounds placementBounds = pickParentNew.GetPlacementBounds();
			Gizmos.color = new Color(1f, 1f, 0f);
			DrawFatWireCube(placementBounds.center, placementBounds.size);
		}
		if (showPlacementBounds)
		{
			Bounds placementBounds2 = GetPlacementBounds();
			Gizmos.color = Color.white;
			DrawFatWireCube(placementBounds2.center, placementBounds2.size);
		}
		if (!showChildrenBounds || placementChildren == null)
		{
			return;
		}
		foreach (RemoteControl placementChild in placementChildren)
		{
			if (placementChild != null)
			{
				Bounds placementBounds3 = placementChild.GetPlacementBounds();
				Gizmos.color = new Color(0f, 1f, 0f);
				DrawFatWireCube(placementBounds3.center, placementBounds3.size);
			}
		}
	}

	private void DrawFatWireCube(Vector3 center, Vector3 size)
	{
		Gizmos.DrawWireCube(center, size);
		Gizmos.DrawWireCube(center + Vector3.right * 0.005f, size);
		Gizmos.DrawWireCube(center + Vector3.left * 0.005f, size);
		Gizmos.DrawWireCube(center + Vector3.up * 0.005f, size);
		Gizmos.DrawWireCube(center + Vector3.down * 0.005f, size);
		Gizmos.DrawWireCube(center + Vector3.forward * 0.005f, size);
		Gizmos.DrawWireCube(center + Vector3.back * 0.005f, size);
		Gizmos.DrawWireCube(center + Vector3.right * 0.0005f, size);
		Gizmos.DrawWireCube(center + Vector3.left * 0.0005f, size);
		Gizmos.DrawWireCube(center + Vector3.up * 0.0005f, size);
		Gizmos.DrawWireCube(center + Vector3.down * 0.0005f, size);
		Gizmos.DrawWireCube(center + Vector3.forward * 0.0005f, size);
		Gizmos.DrawWireCube(center + Vector3.back * 0.0005f, size);
	}

	private void OnEnable()
	{
		CalculateDisplacement();
	}

	private void Update()
	{
		if (!Application.isEditor || Application.isPlaying)
		{
			Object.DestroyImmediate(base.gameObject);
		}
		else if (controller == null)
		{
			Object.DestroyImmediate(base.gameObject);
		}
		else
		{
			Refresh();
		}
	}

	private void OnRenderObject()
	{
		Refresh();
	}

	public void SetPosition(Vector3 newPosition)
	{
		base.transform.position = newPosition;
		CalculateDisplacement();
		UpdatePosition();
	}

	public void Refresh(bool forced = false)
	{
		if (!Application.isEditor || Application.isPlaying)
		{
			return;
		}
		bool flag = forced;
		if (!flag && !Utils.AreEqualBounds(oldPlacementParentBounds, GetPlacementParentBounds()))
		{
			flag = true;
		}
		if (!flag && !Utils.AreEqualBounds(oldPlacementBounds, GetPlacementBounds()))
		{
			flag = true;
		}
		if (!flag && (alignX != alignXOld || alignY != alignYOld || alignZ != alignZOld))
		{
			flag = true;
		}
		if (!flag && (alignXOffset != alignXOffsetOld || alignYOffset != alignYOffsetOld || alignZOffset != alignZOffsetOld))
		{
			flag = true;
		}
		alignXOld = alignX;
		alignYOld = alignY;
		alignZOld = alignZ;
		alignXOffsetOld = alignXOffset;
		alignYOffsetOld = alignYOffset;
		alignZOffsetOld = alignZOffset;
		if (!flag)
		{
			if (recentUpdated < 2)
			{
				recentUpdated++;
			}
			return;
		}
		recentUpdated = 0;
		bool flag2 = false;
		if (!Utils.AreEqualBounds(oldPlacementParentBounds, GetPlacementParentBounds()))
		{
			flag2 = true;
		}
		if (!flag2)
		{
			CalculateDisplacement();
		}
		UpdatePosition();
		if (flag2)
		{
			oldPlacementParentBounds = Utils.CopyOfBounds(GetPlacementParentBounds());
		}
		if (manualScale)
		{
			base.transform.localScale = scale;
		}
		EnforceAlignment(false);
		scale = base.transform.localScale;
		oldPlacementBounds = Utils.CopyOfBounds(GetPlacementBounds());
	}

	public Bounds GetPlacementBounds()
	{
		return base.GetComponent<Renderer>().bounds;
	}

	public Bounds GetPlacementParentBounds()
	{
		if (placementParent != null)
		{
			return placementParent.GetPlacementBounds();
		}
		return new Bounds(Vector3.zero, Vector3.zero);
	}

	public Vector3 GetPlacementParentPosition()
	{
		if (placementParent != null)
		{
			return placementParent.transform.position;
		}
		return Vector3.zero;
	}

	public void DoRecursiveCalculateDisplacement()
	{
		if (placementChildren != null)
		{
			foreach (RemoteControl placementChild in placementChildren)
			{
				if (placementChild != null)
				{
					placementChild.DoRecursiveCalculateDisplacement();
				}
			}
		}
		CalculateDisplacement();
	}

	public void CalculateDisplacement()
	{
		if (placementParent == null)
		{
			displacement = base.transform.position;
		}
		else
		{
			displacement = base.transform.position - placementParent.transform.position;
		}
	}

	public void CalculateDisplacementExceptAlignment()
	{
		if (placementParent != null)
		{
			if (alignX != 0)
			{
				displacement.x = base.transform.position.x - placementParent.transform.position.x;
			}
			if (alignY != 0)
			{
				displacement.y = base.transform.position.y - placementParent.transform.position.y;
			}
			if (alignZ != 0)
			{
				displacement.z = base.transform.position.z - placementParent.transform.position.z;
			}
		}
	}

	public void UpdatePosition()
	{
		if (placementParent == null)
		{
			base.transform.position = displacement;
		}
		else
		{
			base.transform.position = placementParent.transform.position + displacement;
		}
	}

	public void SetPlacementParent(RemoteControl par)
	{
		if (placementParent != par)
		{
			if (placementParent != null)
			{
				placementParent.RemovePlacementChild(this);
			}
			if (par != null)
			{
				par.AddPlacementChild(this);
			}
		}
		placementParent = par;
		if (placementParent == null)
		{
			alignX = BoxAlignment.None;
			alignY = BoxAlignment.None;
			alignZ = BoxAlignment.None;
		}
		CalculateDisplacement();
	}

	public void AddPlacementChild(RemoteControl child)
	{
		if (placementChildren == null)
		{
			placementChildren = new List<RemoteControl>();
		}
		if (!placementChildren.Contains(child))
		{
			placementChildren.Add(child);
		}
	}

	public void RemovePlacementChild(RemoteControl child)
	{
		if (placementChildren == null)
		{
			placementChildren = new List<RemoteControl>();
		}
		if (placementChildren.Contains(child))
		{
			placementChildren.Remove(child);
		}
	}

	public bool ContainsPlacementChildInSubtree(RemoteControl search)
	{
		Stack<RemoteControl> stack = new Stack<RemoteControl>();
		stack.Push(this);
		for (int num = 1; num > 0; num = stack.Count)
		{
			RemoteControl remoteControl = stack.Pop();
			if (remoteControl != null)
			{
				if (remoteControl == search)
				{
					return true;
				}
				if (remoteControl.placementChildren != null)
				{
					foreach (RemoteControl placementChild in remoteControl.placementChildren)
					{
						if (placementChild == search)
						{
							return true;
						}
						stack.Push(placementChild);
					}
				}
			}
		}
		return false;
	}

	public bool ContainsPlacementChild(RemoteControl child)
	{
		if (placementChildren == null)
		{
			placementChildren = new List<RemoteControl>();
		}
		return placementChildren.Contains(child);
	}

	public void DetachPlacementChildren()
	{
		if (placementChildren == null)
		{
			return;
		}
		for (int count = placementChildren.Count; count > 0; count = placementChildren.Count)
		{
			RemoteControl remoteControl = placementChildren[0];
			if (remoteControl != null)
			{
				remoteControl.SetPlacementParent(null);
			}
			else
			{
				placementChildren.Remove(remoteControl);
			}
		}
	}

	public void DoRecursiveHierarchyParenting(RemoteControl topRemote = null)
	{
		if (placementChildren != null)
		{
			foreach (RemoteControl placementChild in placementChildren)
			{
				if (placementChild != null)
				{
					placementChild.DoRecursiveHierarchyParenting(topRemote);
				}
			}
		}
		if (topRemote == null || topRemote != this)
		{
			HierarchyParenting();
		}
	}

	public void DoRecursiveHierarchyUnparenting(RemoteControl topRemote = null)
	{
		if (placementChildren != null)
		{
			foreach (RemoteControl placementChild in placementChildren)
			{
				if (placementChild != null)
				{
					placementChild.DoRecursiveHierarchyUnparenting(topRemote);
				}
			}
		}
		if (topRemote == null || topRemote != this)
		{
			HierarchyUnparenting();
		}
	}

	public void DoRecursiveRotateAlignment(Vector3 toRotate, RemoteControl topRemote = null)
	{
		if (placementChildren != null)
		{
			foreach (RemoteControl placementChild in placementChildren)
			{
				if (placementChild != null)
				{
					placementChild.DoRecursiveRotateAlignment(toRotate, topRemote);
				}
			}
		}
		if (topRemote == null || topRemote != this)
		{
			RotateAlignment(toRotate);
		}
	}

	private void HierarchyParenting()
	{
		if (placementParent != null)
		{
			base.transform.parent = placementParent.transform;
		}
	}

	private void HierarchyUnparenting()
	{
		base.transform.parent = remotesParent;
	}

	private void RotateAlignment(Vector3 toRotate)
	{
		BoxAlignment boxAlignment = alignX;
		BoxAlignment boxAlignment2 = alignY;
		BoxAlignment boxAlignment3 = alignZ;
		if (toRotate.y == 90f)
		{
			float num = alignZOffset;
			float num2 = 0f - alignXOffset;
			alignXOffset = num;
			alignZOffset = num2;
			boxAlignment = alignZ;
			switch (alignX)
			{
			case BoxAlignment.LeftOut:
				boxAlignment3 = BoxAlignment.RightOut;
				break;
			case BoxAlignment.LeftIn:
				boxAlignment3 = BoxAlignment.RightIn;
				break;
			case BoxAlignment.Center:
				boxAlignment3 = BoxAlignment.Center;
				break;
			case BoxAlignment.RightIn:
				boxAlignment3 = BoxAlignment.LeftIn;
				break;
			case BoxAlignment.RightOut:
				boxAlignment3 = BoxAlignment.LeftOut;
				break;
			case BoxAlignment.None:
				boxAlignment3 = BoxAlignment.None;
				break;
			}
		}
		if (toRotate.y == -90f)
		{
			float num3 = 0f - alignZOffset;
			float num4 = alignXOffset;
			alignXOffset = num3;
			alignZOffset = num4;
			boxAlignment3 = alignX;
			switch (alignZ)
			{
			case BoxAlignment.LeftOut:
				boxAlignment = BoxAlignment.RightOut;
				break;
			case BoxAlignment.LeftIn:
				boxAlignment = BoxAlignment.RightIn;
				break;
			case BoxAlignment.Center:
				boxAlignment = BoxAlignment.Center;
				break;
			case BoxAlignment.RightIn:
				boxAlignment = BoxAlignment.LeftIn;
				break;
			case BoxAlignment.RightOut:
				boxAlignment = BoxAlignment.LeftOut;
				break;
			case BoxAlignment.None:
				boxAlignment = BoxAlignment.None;
				break;
			}
		}
		alignX = boxAlignment;
		alignY = boxAlignment2;
		alignZ = boxAlignment3;
	}

	public void RotateWithChildren(Vector3 toRotate)
	{
		DoRecursiveHierarchyParenting(this);
		base.transform.rotation = base.transform.rotation * Quaternion.Euler(toRotate);
		DoRecursiveHierarchyUnparenting(this);
		DoRecursiveRotateAlignment(toRotate, this);
		DoRecursiveCalculateDisplacement();
	}

	public void Duplicate()
	{
	}

	public void ResetToPrefab()
	{
	}

	private void EnforceAlignment(bool affectDisplacement = true)
	{
		switch (alignX)
		{
		case BoxAlignment.LeftOut:
			AlignXLeftOut(affectDisplacement);
			break;
		case BoxAlignment.LeftIn:
			AlignXLeftIn(affectDisplacement);
			break;
		case BoxAlignment.Center:
			AlignXCenter(affectDisplacement);
			break;
		case BoxAlignment.RightIn:
			AlignXRightIn(affectDisplacement);
			break;
		case BoxAlignment.RightOut:
			AlignXRightOut(affectDisplacement);
			break;
		}
		switch (alignY)
		{
		case BoxAlignment.LeftOut:
			AlignYLeftOut(affectDisplacement);
			break;
		case BoxAlignment.LeftIn:
			AlignYLeftIn(affectDisplacement);
			break;
		case BoxAlignment.Center:
			AlignYCenter(affectDisplacement);
			break;
		case BoxAlignment.RightIn:
			AlignYRightIn(affectDisplacement);
			break;
		case BoxAlignment.RightOut:
			AlignYRightOut(affectDisplacement);
			break;
		}
		switch (alignZ)
		{
		case BoxAlignment.LeftOut:
			AlignZLeftOut(affectDisplacement);
			break;
		case BoxAlignment.LeftIn:
			AlignZLeftIn(affectDisplacement);
			break;
		case BoxAlignment.Center:
			AlignZCenter(affectDisplacement);
			break;
		case BoxAlignment.RightIn:
			AlignZRightIn(affectDisplacement);
			break;
		case BoxAlignment.RightOut:
			AlignZRightOut(affectDisplacement);
			break;
		}
	}

	public void SetAlignX(BoxAlignment newAlign)
	{
		if (newAlign == alignX)
		{
			alignX = BoxAlignment.None;
		}
		else
		{
			alignX = newAlign;
		}
	}

	public void AlignXLeftOut(bool affectDisplacement = true)
	{
		Bounds placementBounds = GetPlacementBounds();
		Bounds placementParentBounds = GetPlacementParentBounds();
		base.transform.position = Utils.GetPositionAlignXLeftOut(placementBounds, placementParentBounds) + Vector3.right * alignXOffset;
		if (affectDisplacement)
		{
			CalculateDisplacement();
		}
	}

	public void AlignXLeftIn(bool affectDisplacement = true)
	{
		Bounds placementBounds = GetPlacementBounds();
		Bounds placementParentBounds = GetPlacementParentBounds();
		base.transform.position = Utils.GetPositionAlignXLeftIn(placementBounds, placementParentBounds) + Vector3.right * alignXOffset;
		if (affectDisplacement)
		{
			CalculateDisplacement();
		}
	}

	public void AlignXCenter(bool affectDisplacement = true)
	{
		Bounds placementBounds = GetPlacementBounds();
		Bounds placementParentBounds = GetPlacementParentBounds();
		base.transform.position = Utils.GetPositionAlignXCenter(placementBounds, placementParentBounds) + Vector3.right * alignXOffset;
		if (affectDisplacement)
		{
			CalculateDisplacement();
		}
	}

	public void AlignXRightIn(bool affectDisplacement = true)
	{
		Bounds placementBounds = GetPlacementBounds();
		Bounds placementParentBounds = GetPlacementParentBounds();
		base.transform.position = Utils.GetPositionAlignXRightIn(placementBounds, placementParentBounds) + Vector3.right * alignXOffset;
		if (affectDisplacement)
		{
			CalculateDisplacement();
		}
	}

	public void AlignXRightOut(bool affectDisplacement = true)
	{
		Bounds placementBounds = GetPlacementBounds();
		Bounds placementParentBounds = GetPlacementParentBounds();
		base.transform.position = Utils.GetPositionAlignXRightOut(placementBounds, placementParentBounds) + Vector3.right * alignXOffset;
		if (affectDisplacement)
		{
			CalculateDisplacement();
		}
	}

	public void SetAlignY(BoxAlignment newAlign)
	{
		if (newAlign == alignY)
		{
			alignY = BoxAlignment.None;
		}
		else
		{
			alignY = newAlign;
		}
	}

	public void AlignYLeftOut(bool affectDisplacement = true)
	{
		Bounds placementBounds = GetPlacementBounds();
		Bounds placementParentBounds = GetPlacementParentBounds();
		base.transform.position = Utils.GetPositionAlignYLeftOut(placementBounds, placementParentBounds) + Vector3.up * alignYOffset;
		if (affectDisplacement)
		{
			CalculateDisplacement();
		}
	}

	public void AlignYLeftIn(bool affectDisplacement = true)
	{
		Bounds placementBounds = GetPlacementBounds();
		Bounds placementParentBounds = GetPlacementParentBounds();
		base.transform.position = Utils.GetPositionAlignYLeftIn(placementBounds, placementParentBounds) + Vector3.up * alignYOffset;
		if (affectDisplacement)
		{
			CalculateDisplacement();
		}
	}

	public void AlignYCenter(bool affectDisplacement = true)
	{
		Bounds placementBounds = GetPlacementBounds();
		Bounds placementParentBounds = GetPlacementParentBounds();
		base.transform.position = Utils.GetPositionAlignYCenter(placementBounds, placementParentBounds) + Vector3.up * alignYOffset;
		if (affectDisplacement)
		{
			CalculateDisplacement();
		}
	}

	public void AlignYRightIn(bool affectDisplacement = true)
	{
		Bounds placementBounds = GetPlacementBounds();
		Bounds placementParentBounds = GetPlacementParentBounds();
		base.transform.position = Utils.GetPositionAlignYRightIn(placementBounds, placementParentBounds) + Vector3.up * alignYOffset;
		if (affectDisplacement)
		{
			CalculateDisplacement();
		}
	}

	public void AlignYRightOut(bool affectDisplacement = true)
	{
		Bounds placementBounds = GetPlacementBounds();
		Bounds placementParentBounds = GetPlacementParentBounds();
		base.transform.position = Utils.GetPositionAlignYRightOut(placementBounds, placementParentBounds) + Vector3.up * alignYOffset;
		if (affectDisplacement)
		{
			CalculateDisplacement();
		}
	}

	public void SetAlignZ(BoxAlignment newAlign)
	{
		if (newAlign == alignZ)
		{
			alignZ = BoxAlignment.None;
		}
		else
		{
			alignZ = newAlign;
		}
	}

	public void AlignZLeftOut(bool affectDisplacement = true)
	{
		Bounds placementBounds = GetPlacementBounds();
		Bounds placementParentBounds = GetPlacementParentBounds();
		base.transform.position = Utils.GetPositionAlignZLeftOut(placementBounds, placementParentBounds) + Vector3.forward * alignZOffset;
		if (affectDisplacement)
		{
			CalculateDisplacement();
		}
	}

	public void AlignZLeftIn(bool affectDisplacement = true)
	{
		Bounds placementBounds = GetPlacementBounds();
		Bounds placementParentBounds = GetPlacementParentBounds();
		base.transform.position = Utils.GetPositionAlignZLeftIn(placementBounds, placementParentBounds) + Vector3.forward * alignZOffset;
		if (affectDisplacement)
		{
			CalculateDisplacement();
		}
	}

	public void AlignZCenter(bool affectDisplacement = true)
	{
		Bounds placementBounds = GetPlacementBounds();
		Bounds placementParentBounds = GetPlacementParentBounds();
		base.transform.position = Utils.GetPositionAlignZCenter(placementBounds, placementParentBounds) + Vector3.forward * alignZOffset;
		if (affectDisplacement)
		{
			CalculateDisplacement();
		}
	}

	public void AlignZRightIn(bool affectDisplacement = true)
	{
		Bounds placementBounds = GetPlacementBounds();
		Bounds placementParentBounds = GetPlacementParentBounds();
		base.transform.position = Utils.GetPositionAlignZRightIn(placementBounds, placementParentBounds) + Vector3.forward * alignZOffset;
		if (affectDisplacement)
		{
			CalculateDisplacement();
		}
	}

	public void AlignZRightOut(bool affectDisplacement = true)
	{
		Bounds placementBounds = GetPlacementBounds();
		Bounds placementParentBounds = GetPlacementParentBounds();
		base.transform.position = Utils.GetPositionAlignZRightOut(placementBounds, placementParentBounds) + Vector3.forward * alignZOffset;
		if (affectDisplacement)
		{
			CalculateDisplacement();
		}
	}
}
